import {
  forwardRef,
  lazy,
  Ref,
  Suspense,
  useEffect,
  useImperativeHandle,
  useMemo,
} from "react";
import "./DesignerView.less";
import layerManager from "../manager/LayerManager";
import { observer } from "mobx-react";
import Loading from "../../json-schema/ui/loading/Loading";
import DesignerLoaderFactory from "../loader/DesignerLoaderFactory";
import layerBuilder from "../left/layer-list/LayerBuilder";
import { DesignerMode, IProjectInfo, SaveType } from "../DesignerType";
import canvasManager from "../header/items/canvas/CanvasManager";
import designerManager from "../manager/DesignerManager";
import "../../designer/resource/font/FontGlobal.css";
import ScaleAction from "../../framework/core/ScaleAction";
import { getControllers } from "framework/utils/LayerUtil";
import { IotDeviceData } from "_common/DataType";
import operatorMap from "framework/operate";
import FileUtil from "utils/FileUtil";
import { ViewerState } from "components";

const ScreenFit = lazy(() => import("../../framework/screen-fit/ScreenFit"));

export interface DesignerViewProps {
  width: number;
  height: number;
  onClick?: (deviceCode: string) => void;
}

export type DesignerViewInstance = {
  /**
   * 加载场景
   * @param dataJson 场景json数据
   * @returns
   */
  load: (dataJson: string) => void;

  /**
   * 更新设备数据
   * @param data 设备
   * @returns
   * */
  updateData: (data: IotDeviceData) => void;

  // 销毁
  destroy: () => void;
};
const staticType = SaveType.LOCAL; // 只在本地存储
const DesignerView = forwardRef(
  (props: DesignerViewProps, ref: Ref<DesignerViewInstance>) => {
    const { onClick } = props;

    useEffect(() => {
      ViewerState.handleClick = (data) => {
        onClick?.(data);
      };
      return () => {
        designerManager.destroy();
      };
    }, []);

    useImperativeHandle(ref, () => ({
      updateData: updateDeviceData,
      load: (dataJson) => loadProject(dataJson),
      destroy: () => {
        designerManager.destroy();
      },
    }));

    const initialization = async (project: IProjectInfo) => {
      const pid = await operatorMap[staticType].createProject(project);
      DesignerLoaderFactory.getLoader(DesignerMode.EDIT).load(pid, staticType);
      return pid;
    };

    const loadProject = async (dataJson: string) => {
      // designerManager.destroy();
      // 加载数据前先初始化数据
      const importData = JSON.parse(dataJson);
      const projectId = importData.id;
      // 初始化
      const projectData = importData.data;
      const elemConfigs = projectData?.layerManager?.elemConfigs;
      const promises: Promise<void>[] = [];
      if (elemConfigs) {
        Object.keys(elemConfigs).forEach((key) => {
          const item = elemConfigs[key];
          if (
            item.base.type === "BaseImage" &&
            (item.style.localUrl as string)?.startsWith("blob")
          ) {
            // 将 blob 数据转换为 base64，并将异步操作添加到 promises 数组中
            promises.push(
              FileUtil.base64ToBlob(item.style.localUrl as string).then(
                (res: string | boolean) => {
                  if (res) item.style.localUrl = res;
                  else {
                    console.error(
                      `${item.base.id + "_" + item.base.name} 图片blob转换失败, ${item.style.localUrl}`
                    );
                  }
                }
              )
            );
          }
        });
      }
      await Promise.all(promises);
      layerManager.setEnableEvent(true);
      const project: IProjectInfo = {
        name: "",
        des: "",
        id: projectId,
        saveType: staticType,
        dataJson: JSON.stringify(projectData),
      };
      await initialization(project);
    };

    const { loaded } = designerManager;
    const { compController } = layerManager!;

    const updateDeviceData = (data: IotDeviceData) => {
      if (data && data.dtCode) {
        const controllers = getControllers(compController, data.dtCode);
        controllers?.forEach((a) => {
          a.changeData(data);
        });
      }
    };

    const baseNode = useMemo(() => {
      const {
        canvasConfig: { width, height, adaptationType },
      } = canvasManager;
      return loaded ? (
        <Suspense fallback={<Loading />}>
          <ScreenFit
            width={props.width!}
            height={props.height!}
            mode={adaptationType}
            scaleChange={(xScale, yScale) => {
              ScaleAction.doScale(xScale, yScale);
              // ScaleAction.doScale(xScale, yScale);
            }}
          >
            <div
              style={{
                width: width,
                height: height,
                // background: "black",
                overflow: "hidden",
                position: "relative",
                transformOrigin: "left top",
                transform: `scale(${props.width / (width ?? 0)},${props.height / (height ?? 0)})`,
              }}
            >
              {layerBuilder.buildCanvasComponents(layerManager.layerConfigs)}
            </div>
          </ScreenFit>
        </Suspense>
      ) : (
        <Loading width={props.width} height={props.height} />
      );
    }, [
      loaded,
      canvasManager,
      layerManager.layerConfigs,
      props.height,
      props.width,
    ]);

    return baseNode;
  }
);

export default observer(DesignerView);
